/*
 * Copyright (c) 2002,2016 Mario de Sousa (msousa@fe.up.pt)
 *
 * This file is part of the Modbus library for Beremiz and matiec.
 *
 * This Modbus library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this Modbus library.  If not, see <http://www.gnu.org/licenses/>.
 *
 * This code is made available on the understanding that it will not be
 * used in safety-critical situations without a full and competent review.
 */

#ifndef PLC_MB_ADDR_H
#define PLC_MB_ADDR_H
#ifndef INADDR_ANY
//#define INADDR_ANY 0
#endif

#include <stdint.h>
//#include <pthread.h>

#if defined(PLC_IS_APP)

#if defined(windows_x86) // platform=windows_x86
// #include <windows.h>
#include <pthread.h>
#pragma comment(lib, "wsock32.lib")
#endif

#else
// #include <sys/socket.h>
// #include <netinet/in.h>
#ifdef ARDUINO

#include <Arduino.h>

#elif defined(windows_x86) // platform=windows_x86

//#include <windows.h>
#include <pthread.h>

#pragma comment(lib, "wsock32.lib")
#else

#endif

#endif

/* Library Error codes */
#define PORT_FAILURE -101
#define INTERNAL_ERROR -102
#define MODBUS_TIMEOUT -103
#define INVALID_FRAME -104
#define MODBUS_ERROR -105
typedef unsigned char u8;
typedef unsigned short u16;

#if !defined(LINUX)
typedef unsigned long long u64;
#endif
/* NOTE: Modbus error codes are defined in mb_util.h */

#include "mb_addr.h"


typedef struct
{
    const char *location;
    u8 slave_id;
    node_addr_t node_address;
    int init_state; // store how far along the server's initialization has progressed

    memarea *mem_area_robits;
    memarea *mem_area_rwbits;
    memarea *mem_area_rowords;
    memarea *mem_area_words;
    short prev_error; // error code of the last printed error message (0 when no error)
    u8 enable;
    uint32_t errcount;
    uint32_t okcount;
    u8 inwrite;
    void *thread_id; // thread handling this server
    u8 flag;
    int fd;
    void *nd;
} server_node_t;
// // Used by the Modbus client plugin
typedef enum
{
    req_input,
    req_output,
    no_request /* just for tests to quickly disable a request */
} iotype_t;

typedef struct
{
    const char *location;
    int client_node_id;
    u8 slave_id;
    node_addr_t node_address;
    iotype_t req_type;
    u8 mb_function;
    u16 address;
    u16 count;
    int retries;
    u8 error_code;    // modbus error code (if any) of current request
    short prev_error; // error code of the last printed error message (0 when no error)
    uint32_t resp_timeout;
    // buffer used to store located PLC variables
    u16 *plcv_buffer;
    // buffer used to store data coming from / going to server
    u16 *coms_buffer;
    void *coms_buf_mutex; // mutex to access coms_buffer[]
    u8 enable;
    uint32_t period;
    uint32_t delay_before;
    u8 crc_reverse;
    uint32_t okcount;
    uint32_t errcount;
    uint32_t tick;
} client_request_t;
// Used by the Modbus client node
typedef struct
{
    const char *location;
    node_addr_t node_address;
    int req_nrs; //请求数量
    int init_state; // store how far along the client's initialization has progressed
    uint32_t comm_period;
    client_request_t *req;
    short prev_error; // error code of the last printed error message (0 when no error)
    void *thread_id;  // thread handling this server
    u8 flag;
    int fd;
    void *nd;
} client_node_t;
#define CLIENT_RUNNING 1
typedef struct
{
    int (*mb_slave_and_master_init)(int nd_count_tcp, int nd_count_rtu, int nd_count_ascii);

    int (*mb_slave_and_master_done)();
} mb_abi_t;
typedef struct
{
    int (*mb_request_init)(client_request_t *);

    int (*mb_request_lock)(client_request_t *);

    int (*mb_request_trylock)(client_request_t *);

    int (*mb_request_unlock)(client_request_t *);

    int (*mb_request_close)(client_request_t *);
} mb_request_abi_t;
typedef struct
{
    int (*mb_master_connect)(client_node_t *);

    int (*mb_master_close)(client_node_t *);
} mb_master_abi_t;

typedef struct
{
    int (*mb_slave_init)(server_node_t *);

    int (*mb_slave_close)(server_node_t *);
} mb_slave_abi_t;

extern const mb_abi_t mb_abi;
extern const mb_request_abi_t mb_request_abi;
extern const mb_master_abi_t mb_master_abi;
extern const mb_slave_abi_t mb_slave_abi;
#endif /* PLC_MB_ADDR_H */
